home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / glimpse-2.1 / index / dir.c < prev    next >
C/C++ Source or Header  |  1995-05-16  |  15KB  |  517 lines

  1. /* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal.  All Rights Reserved. */
  2. /* ./glimpse/index/dir.c */
  3.  
  4. /* The function of the program is to traverse the
  5.    direcctory tree and print the size of the files in the tree.
  6.    This program is derived from the C-programming language book
  7.    It opens a directory file using opendir system call, and use readdir()
  8.    to read each entry of the directory.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #if    DIRENT
  14. #include <dirent.h>
  15. #else    /*DIRENT*/
  16. #include <sys/dir.h>
  17. #endif    /*DIRENT*/
  18. #include <sys/stat.h>
  19. #include <fcntl.h>
  20. #define BUFSIZE 256
  21. #define DIRSIZE 14
  22. #include "glimpse.h"
  23. #undef MAX_LIST
  24. #define MAX_LIST 100000
  25.  
  26. #if    BG_DEBUG
  27. extern FILE *LOGFILE;
  28. #endif    /*BG_DEBUG*/
  29. extern FILE *MESSAGEFILE;
  30. int ndx = 0;                    /* file index */
  31. extern char *name_list[MAX_LIST];  /* store the file names */
  32. extern int  *size_list;   /* store the sizes of the files */
  33. extern int disable_list[FILEMASK_SIZE];   /* store whether to DISABLE indexing or not */
  34. extern int  file_num;
  35. extern int  file_id;    /* borrowed from filetype.c */
  36. extern char INDEX_DIR[MAX_LINE_LEN];
  37. extern int AddToIndex;
  38. extern int FastIndex;
  39. extern int OneFilePerBlock;
  40. extern int IncludeHigherPriority;
  41. extern int BuildDictionaryExisting;
  42. extern int printed_warning;
  43. extern int p_table[];
  44. extern FILE *STATFILE;
  45.  
  46. extern int IndexableFile;
  47. extern int files_per_partition;
  48. extern int new_partition;
  49. extern int files_in_partition;
  50. extern struct stat istbuf;    /* imported from glimpse.c */
  51. extern int memory_usage;
  52. extern int mask_int[];
  53.  
  54. extern char exin_argv[8];
  55. extern int exin_argc;
  56. extern char current_dir_buf[2*MAX_LINE_LEN + 4];    /* must have space to store pattern after directory name */
  57. extern unsigned char dummypat[MAX_PAT];
  58. extern int dummylen;
  59. extern FILE *dummyout;
  60.  
  61. extern struct stat excstbuf;
  62. extern struct stat incstbuf;
  63.  
  64. extern int num_filter;
  65. extern int filter_len[MAX_FILTER];
  66. extern CHAR *filter[MAX_FILTER];
  67. extern CHAR *filter_command[MAX_FILTER];
  68.  
  69. /*
  70.  * Exclude/Include priorities with exclude > include (IncludeHigherPriority = OFF = default):
  71.  * 1. Command line arguments (inclusion --> exclude list is never applied)
  72.  * 2. Exclude list (exclusion)
  73.  * 3. Include list (inclusion)
  74.  * 5. Symbolic links (exclusion --> applying exclude list is unnecessary)
  75.  * 4. filetype (exclusion)
  76.  * 
  77.  * Exclude/Include priorities with include > exclude (IncludeHigherPriority = ON = -i):
  78.  * 1. Command line arguments (inclusion --> exclude list is never applied)
  79.  * 2. Include list (inclusion)
  80.  * 3. Symbolic links (exclusion --> applying exclude list is unnecessary)
  81.  * 3. Exclude list (exclusion)
  82.  * 4. filetype (exclusion)
  83.  */
  84.  
  85. char outname[MAX_LINE_LEN];
  86. char inname[MAX_LINE_LEN];
  87.  
  88. fsize(name, pat, pat_len, num_pat, inc, inc_len, num_inc, toplevel)
  89. char *name;
  90. char **pat;
  91. int *pat_len;
  92. int num_pat;
  93. char **inc;
  94. int *inc_len;
  95. int num_inc;
  96. int toplevel;
  97. {
  98.     struct stat stbuf;
  99.     int i;
  100.     int fileindex = -1;
  101.     int force_include = 0;
  102.     int len_current_dir_buf = strlen(current_dir_buf) + 1;    /* includes the '\0' which is going to be replaced by '\n' below */
  103.     int name_len;
  104.  
  105.     name_len = strlen(name);    /* name[name_len] is '\0' */
  106.  
  107. #ifdef    SW_DEBUG
  108.     printf("num_pat= %d num_inc= %d\n", num_pat, num_inc);
  109.     printf("name= %s\n", name);
  110. #endif
  111.  
  112.     /*
  113.      * Find out what to exclude, what to include and skip
  114.      * over symbolic links that don't HAVE to be included.
  115.      * Some Extra get_filename_index calls are done but
  116.      * that won't cost you anything (just #ing twice).
  117.      */
  118.  
  119.     /* Check if cache set in glimpse.c is correct */
  120.     if (!IndexableFile && FastIndex && ((fileindex = get_filename_index(name, name_list, file_num)) != -1) && (disable_list[block2index(fileindex)] & mask_int[fileindex % (8*sizeof(int))])) {
  121.         if (num_pat <= 0) {
  122.         if (num_inc <= 0) return 0;
  123.         else if (incstbuf.st_ctime <= istbuf.st_ctime) return 0;
  124.         }
  125.         else {
  126.         if (num_inc <= 0) {
  127.             if (excstbuf.st_ctime <= istbuf.st_ctime) return 0;
  128.         }
  129.         else if ((excstbuf.st_ctime <= istbuf.st_ctime) && (incstbuf.st_ctime <= istbuf.st_ctime)) return 0;
  130.         }
  131.     }
  132.  
  133. #define PROCESS_EXIT \
  134. {\
  135.     if (AddToIndex || FastIndex) {\
  136.         if ((fileindex = get_filename_index(name, name_list, file_num)) != -1) \
  137.             remove_filename(fileindex, new_partition);\
  138.     }\
  139. }
  140.  
  141. #define PROCESS_EXCLUDE \
  142. {\
  143.     if (!toplevel) for(i=0; i<num_pat; i++) {    /* bg: 15/mar/94 */\
  144.         if (pat_len[i] > 0) {\
  145.             name[name_len] = '\0';\
  146.             if (strstr(name, pat[i]) != NULL) {\
  147.                 PROCESS_EXIT;\
  148.                 return 0;\
  149.             }\
  150.         }\
  151.         else {    /* must call memagrep */\
  152.             int    ret;\
  153.             name[name_len] = '\n';    /* memagrep wants names to end with '\n': '\0' is not necessary */\
  154.             /* printf("i=%d patlen=%d pat=%s inlen=%d input=%s\n", i, -pat_len[i], pat[i], len_current_dir_buf, current_dir_buf); */\
  155.             if (((pat_len[i] == -2) && (pat[i][0] == '.') && (pat[i][1] == '*')) ||\
  156.                 ((ret = memagrep_search(-pat_len[i], pat[i], len_current_dir_buf, current_dir_buf, 0, dummyout)) > 0))\
  157.             {\
  158.                 /* printf("excluding with %d %s\n", ret, name); */\
  159.                 name[name_len] = '\0';    /* restore */\
  160.                 PROCESS_EXIT;\
  161.                   return 0; \
  162.             }\
  163.             /* else printf("ret=%d\n");*/\
  164.         }\
  165.     }\
  166.     name[name_len] = '\0';\
  167. }
  168.  
  169. #define PROCESS_INCLUDE \
  170. {\
  171.      /*\
  172.      * When include has higher priority, we want to include directories\
  173.      * by default and match the include patterns only against filenames.\
  174.      * Based on bug reports for glimpse-2.1. bg: 2/mar/95.\
  175.       */\
  176.      if (IncludeHigherPriority && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) force_include = 1;\
  177.      else for (i=0; i<num_inc; i++) {    /* bg: 15/mar/94 */\
  178.         if (inc_len[i] > 0) {\
  179.             name[name_len] = '\0';\
  180.             if (strstr(name, inc[i]) != NULL) {\
  181.                 force_include = 1;\
  182.                 break;\
  183.             }\
  184.         }\
  185.         else {    /* must call memagrep */\
  186.             name[name_len] = '\n';    /* memagrep wants names to end with '\n': '\0' is not necessary */\
  187.             /* printf("pat=%s input=%s\n", pat[i], current_dir_buf); */\
  188.             if (((inc_len[i] == -2) && (inc[i][0] == '.') && (inc[i][1] == '*')) ||\
  189.                 (memagrep_search(-inc_len[i], inc[i], len_current_dir_buf, current_dir_buf, 0, dummyout) > 0))\
  190.             {\
  191.                 force_include = 1;\
  192.                 break;\
  193.             }\
  194.         }\
  195.     }\
  196.     if (!force_include) for (i=0; i<num_filter; i++) {    /* bg: 16/sep/94 */\
  197.         if (filter_len[i] > 0) {\
  198.             name[name_len] = '\0';\
  199.             if (strstr(name, filter[i]) != NULL) {\
  200.                 force_include = 1;\
  201.                 break;\
  202.             }\
  203.         }\
  204.         else {    /* must call memagrep */\
  205.             name[name_len] = '\n';    /* memagrep wants names to end with '\n': '\0' is not necessary */\
  206.             /* printf("pat=%s input=%s\n", pat[i], current_dir_buf); */\
  207.             if (((filter_len[i] == -1) && (filter[i][0] == '.') && (filter[i][1] == '*')) ||\
  208.                 (memagrep_search(-filter_len[i], filter[i], len_current_dir_buf, current_dir_buf, 0, dummyout) > 0))\
  209.             {\
  210.                 force_include = 1;\
  211.                 break;\
  212.             }\
  213.         }\
  214.     }\
  215.     name[name_len] = '\0';    /* restore */\
  216.     if (toplevel) force_include = 1;\
  217. }
  218.  
  219.         if(lstat(name, &stbuf) == -1) {
  220.         if (IndexableFile) return 0;
  221.         /* Can happen for command line arguments, not stuff obtained from fsize_directory() */
  222. #if    BG_DEBUG
  223.         fprintf(LOGFILE, "cannot find %s -- not indexing\n", name);
  224. #endif    /*BG_DEBUG*/
  225.         PROCESS_EXIT;
  226.         return 0;
  227.     }
  228.     /* Else lstat has all the requisite information */
  229.  
  230.     if ((stbuf.st_mode & S_IFMT) == S_IFLNK)  {
  231.         if (IndexableFile) return 0;
  232.         PROCESS_INCLUDE;
  233.         if (!force_include) {
  234. #if    BG_DEBUG
  235.             fprintf(LOGFILE, "%s is a symbolic link -- not indexing\n", name);
  236. #endif    /*BG_DEBUG*/
  237.             PROCESS_EXIT;
  238.             return 0;
  239.         }
  240.         if (-1 == stat(name, &stbuf)) {
  241. #if    BG_DEBUG
  242.             fprintf(LOGFILE, "cannot find target of symbolic link %s -- not indexing\n", name);
  243. #endif    /*BG_DEBUG*/
  244.             PROCESS_EXIT;
  245.             return 0;
  246.         }
  247.     }
  248.     else /* if (!IndexableFile) */ {
  249.         /* Put exclude include processing here... stat all the time: that is faster than former! */
  250.         if (FastIndex && ((fileindex = get_filename_index(name, name_list, file_num)) != -1)) {
  251.             /* Don't process exclude/include if the file `name' is older then the index AND the exclude/include file is older then the index */
  252.             if (IncludeHigherPriority) {
  253.                 if (!((stbuf.st_ctime <= istbuf.st_ctime) && (incstbuf.st_ctime <= istbuf.st_ctime)))
  254.                     PROCESS_INCLUDE;
  255.                 if (!force_include && !((stbuf.st_ctime <= istbuf.st_ctime) && (excstbuf.st_ctime <= istbuf.st_ctime)))
  256.                     PROCESS_EXCLUDE;
  257.             }
  258.             else {
  259.                 if (!((stbuf.st_ctime <= istbuf.st_ctime) && (excstbuf.st_ctime <= istbuf.st_ctime)))
  260.                     PROCESS_EXCLUDE;
  261.                 if (!((stbuf.st_ctime <= istbuf.st_ctime) && (incstbuf.st_ctime <= istbuf.st_ctime)))
  262.                     PROCESS_INCLUDE;
  263.             }
  264.         }
  265.         else {    /* Either AddToIndex or fresh indexing or previously excluded file: process exclude and include */
  266.             if (IncludeHigherPriority) {
  267.                 PROCESS_INCLUDE;
  268.                 if (!force_include)
  269.                     PROCESS_EXCLUDE;
  270.             }
  271.             else {
  272.                 PROCESS_EXCLUDE;
  273.                 PROCESS_INCLUDE;
  274.             }
  275.         }
  276.     }
  277.  
  278.     /* Here, the file exists and has not been excluded -- possibly has been included */
  279.  
  280.     if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
  281.         if (-1 == fsize_directory(name, pat, pat_len, num_pat, inc, inc_len, num_inc)) return -1;
  282.     }
  283.         else if ((stbuf.st_mode & S_IFMT) == S_IFREG) {    /* regular file */
  284.         if (IndexableFile) {
  285.         if (!filetype(name, 0)) printf("%s\n", name);
  286.         return 0;
  287.         }
  288.         file_id ++;
  289.         if (BuildDictionaryExisting) {
  290.         /* Don't even store the names of the files that are not uncompressible */
  291.         if (file_num >= MAXNUM_FILE) {
  292.             fprintf(stderr, "Too many files in index: indexing the first %d only.\n", MAXNUM_FILE);
  293.             return -1;
  294.         }
  295.             if (tuncompress_file(name, outname, TC_EASYSEARCH | TC_OVERWRITE | TC_NOPROMPT) <= 0) return 0;
  296.         file_num++;
  297.         name_list[ndx] = (char *) my_malloc(strlen(outname) + 2);
  298.         strcpy(name_list[ndx], outname);
  299.         size_list[ndx++] = stbuf.st_size;
  300.         return 0;
  301.         }
  302.  
  303. #ifdef SW_DEBUG
  304.         printf("%s: ", name);
  305. #endif
  306.  
  307.         if (AddToIndex || FastIndex) {
  308.         if ((fileindex = get_filename_index(name, name_list, file_num)) != -1) {
  309.             size_list[fileindex] = stbuf.st_size;
  310.             if (FastIndex && (stbuf.st_ctime <= istbuf.st_ctime))
  311.             disable_list[block2index(fileindex)] |= mask_int[fileindex % (8*sizeof(int))];
  312.             else { /* AddToIndex or file was modified (=> its type might have changed!) */
  313.             if (filetype(name, 1)) {
  314.                 if (!force_include) {
  315.                 remove_filename(fileindex, new_partition);
  316.                 return 0;
  317.                 }
  318.                 else {
  319. #if    BG_DEBUG
  320.                 fprintf(LOGFILE, "overriding and indexing: %s\n", name);
  321. #endif    /*BG_DEBUG*/
  322.                 }
  323.             }
  324.             disable_list[block2index(fileindex)] &= ~(mask_int[fileindex % (8*sizeof(int))]);
  325.             }
  326.         }
  327.         else {    /* new file not in filenames so no point in checking */
  328.             if(filetype(name, 1)) {
  329.             if (!force_include) return 0;
  330.             else {
  331. #if    BG_DEBUG
  332.                 fprintf(LOGFILE, "overriding and indexing: %s\n", name);
  333. #endif    /*BG_DEBUG*/
  334.             }
  335.             }
  336.  
  337.             if (file_num >= MAXNUM_FILE) {
  338.             fprintf(stderr, "Too many files in index: indexing the first %d only.\n", MAXNUM_FILE);
  339.             return -1;
  340.             }
  341.             name_list[file_num] = (char *)my_malloc(strlen(name) + 2);
  342.             strcpy(name_list[file_num], name);
  343.             size_list[file_num] = stbuf.st_size;
  344.             insert_filename(name_list[file_num], file_num);
  345.             file_num ++;
  346.  
  347.             if (!OneFilePerBlock) {
  348.                 if (files_in_partition + 1 > files_per_partition) {
  349.                 if (new_partition + 1 > MaxNumPartition) {
  350.                 if (!printed_warning) {
  351.                     printed_warning = 1;
  352.                     if (AddToIndex) {
  353.                     fprintf(MESSAGEFILE, "Warning: partition-table overflow! Fresh indexing recommended.n");
  354.                     }
  355.                     else {
  356.                     fprintf(MESSAGEFILE, "Warning: partition-table overflow! Commencing fresh indexing...\n");
  357.                     return -1;
  358.                     }
  359.                 }
  360.                 }
  361.                 else new_partition++;
  362.                 files_in_partition = 0;
  363.                 /* so that we don't get into this if-branch until another files_per_partition new files are seen */
  364.             }
  365.  
  366.             p_table[new_partition] = file_num;
  367.             files_in_partition ++;
  368.             }
  369.         }
  370.         }
  371.         else { /* Fresh indexing: very simple -- add everything */
  372.         if(filetype(name, 1)) {
  373.             if (!force_include) return 0;
  374.             else {
  375. #if    BG_DEBUG
  376.             fprintf(LOGFILE, "overriding and indexing: %s\n", name);
  377. #endif    /*BG_DEBUG*/
  378.             }
  379.         }
  380.         if (file_num >= MAXNUM_FILE) {
  381.             fprintf(stderr, "Too many files in index: indexing the first %d only.\n", MAXNUM_FILE);
  382.             return -1;
  383.         }
  384.         file_num++;
  385.         name_list[ndx] = (char *) my_malloc(strlen(name) + 2);
  386.         strcpy(name_list[ndx], name);
  387.         size_list[ndx++] = stbuf.st_size;
  388.         }
  389.         }
  390.     return 0;
  391. }
  392.  
  393. /* uses the space in the same "name" to get names of files in that directory and calls fsize */
  394. /* pat, pat_len, num_pat, inc, inc_len, num_inc are just used for recursive calls to fsize */
  395. fsize_directory(name, pat, pat_len, num_pat, inc, inc_len, num_inc)
  396. char *name;
  397. char **pat;
  398. int *pat_len;
  399. int  num_pat;
  400. char **inc;
  401. int *inc_len;
  402. int  num_inc;
  403. {
  404. #if    DIRENT
  405.     struct dirent *dp;
  406. #else    /*DIRENT*/
  407.     struct direct *dp;
  408. #endif    /*DIRENT*/
  409.     char *nbp, *nep;
  410.     int i;
  411.     DIR *dirp;
  412.     /*
  413.     printf("in fsize_directory, name= %s\n",name);
  414.     */
  415.     nbp = name + strlen(name);
  416.     if( nbp+DIRSIZE+2 >= name+BUFSIZE ) /* name too long */
  417.     {       fprintf(stderr, "name too long\n");
  418.         return 0;
  419.     }
  420.         if((dirp = opendir(name)) == NULL) {
  421.         fprintf(stderr, "permission denied or non-existent directory: %s\n", name);
  422.         return 0;
  423.     }
  424.     *nbp++ = '/';
  425.         for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
  426.             if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..")==0) 
  427.             goto CONT;
  428.         for(i=0, nep=nbp; dp->d_name[i] != '\0'; i++)
  429.             *nep++ = dp->d_name[i];
  430.         *nep++ = '\0';
  431.         /*
  432.         printf("name= %s\n", name);
  433.         */
  434.         if (-1 == fsize(name, pat, pat_len, num_pat, inc, inc_len, num_inc, 0)) return -1;
  435. CONT:
  436.         i=0;
  437.     }
  438.         closedir (dirp);
  439.     *--nbp = '\0'; /* restore name */
  440.     return 0;
  441. }
  442.  
  443. typedef struct _name_hashelement {
  444.     char    name[MAX_LINE_LEN];
  445.     int    index;
  446.     struct _name_hashelement *next;
  447. } name_hashelement;
  448.  
  449. name_hashelement *name_hashtable[MAX_4K_HASH];
  450.  
  451. /*
  452.  * Returns the index of the name if the it is found amongst the set
  453.  * of files in name_array; -1 otherwise.
  454.  */
  455. int
  456. get_filename_index(name)
  457.     char    *name;
  458. {
  459.     int    index = hash4k(name, strlen(name));
  460.     /* int    skips=0; */
  461.     name_hashelement    *e;
  462.  
  463.     e = name_hashtable[index];
  464.     while((e != NULL) && (strcmp(name, e->name))) {
  465.         /* skips ++; */
  466.         e = e->next;
  467.     }
  468.     /* fprintf(STATFILE, "skips = %d\n", skips); */
  469.     if (e == NULL) return -1;
  470.     return e->index;
  471. }
  472.  
  473. insert_filename(name, name_index)
  474.     char    *name;
  475.     int    name_index;
  476. {
  477.     int    len = strlen(name);
  478.     int    index;
  479.     name_hashelement **pe;
  480.  
  481.     index = hash4k(name, len);
  482.     pe = &name_hashtable[index];
  483.     while((*pe != NULL) && (strcmp((*pe)->name, name))) pe = &(*pe)->next;
  484.     if ((*pe) != NULL) return;
  485.     *pe = (name_hashelement *)my_malloc(sizeof(name_hashelement));
  486.     (*pe)->next = NULL;
  487.     strcpy((*pe)->name, name);
  488.     (*pe)->index = name_index;
  489. }
  490.  
  491. build_filename_hashtable(names, num)
  492.     char    *names[];
  493.     int    num;
  494. {
  495.     int    i;
  496.  
  497.     for (i=0; i<MAX_4K_HASH; i++) name_hashtable[i] = NULL;
  498.     for (i=0; i<num; i++) insert_filename(names[i], i);
  499. }
  500.  
  501. destroy_filename_hashtable()
  502. {
  503.     int    i;
  504.     name_hashelement *e, *t;
  505.  
  506.     for (i=0; i<MAX_4K_HASH; i++) {
  507.         e = name_hashtable[i];
  508.         while(e!=NULL) {
  509.             t = e;
  510.             e = e->next;
  511.             memory_usage -= sizeof(name_hashelement);
  512.             my_free(t, 0);
  513.         }
  514.         name_hashtable[i] = NULL;
  515.     }
  516. }
  517.